#include "nsLatin1Prober.h"
#include "prmem.h"
#include <stdio.h>

#define UDF    0
#define OTH    1
#define ASC    2
#define ASS    3
#define ACV    4
#define ACO    5
#define ASV    6
#define ASO    7
#define CLASS_NUM   8

static const unsigned char Latin1_CharToClass[] = {
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
  ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
  ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC,
  ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH,
  OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS,
  ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS,
  ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS,
  ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH,
  OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH,
  OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF,
  UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH,
  ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO,
  ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV,
  ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH,
  ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO,
  ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO,
  ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV,
  ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH,
  ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO,
};



static const unsigned char Latin1ClassModel[] = {

  0,  0,  0,  0,  0,  0,  0,  0,
  0,  3,  3,  3,  3,  3,  3,  3,
  0,  3,  3,  3,  3,  3,  3,  3,
  0,  3,  3,  3,  1,  1,  3,  3,
  0,  3,  3,  3,  1,  2,  1,  2,
  0,  3,  3,  3,  3,  3,  3,  3,
  0,  3,  1,  3,  1,  1,  1,  3,
  0,  3,  1,  3,  1,  1,  3,  3,
};

void  nsLatin1Prober::Reset( void ) {
  mState = eDetecting;
  mLastCharClass = OTH;
  for( int i = 0; i < FREQ_CAT_NUM; i++ ) {
    mFreqCounter[i] = 0;
  }
}


nsProbingState nsLatin1Prober::HandleData( const char* aBuf, uint32_t aLen ) {
  char *newBuf1 = 0;
  uint32_t newLen1 = 0;
  if( !FilterWithEnglishLetters( aBuf, aLen, &newBuf1, newLen1 ) ) {
    newBuf1 = ( char* )aBuf;
    newLen1 = aLen;
  }
  unsigned char charClass;
  unsigned char freq;
  for( uint32_t i = 0; i < newLen1; i++ ) {
    charClass = Latin1_CharToClass[( unsigned char )newBuf1[i]];
    freq = Latin1ClassModel[mLastCharClass * CLASS_NUM + charClass];
    if( freq == 0 ) {
      mState = eNotMe;
      break;
    }
    mFreqCounter[freq]++;
    mLastCharClass = charClass;
  }
  if( newBuf1 != aBuf ) {
    PR_FREEIF( newBuf1 );
  }
  return mState;
}

float nsLatin1Prober::GetConfidence( void ) {
  if( mState == eNotMe ) {
    return 0.01f;
  }
  float confidence;
  uint32_t total = 0;
  for( int32_t i = 0; i < FREQ_CAT_NUM; i++ ) {
    total += mFreqCounter[i];
  }
  if( !total ) {
    confidence = 0.0f;
  } else {
    confidence = mFreqCounter[3] * 1.0f / total;
    confidence -= mFreqCounter[1] * 20.0f / total;
  }
  if( confidence < 0.0f ) {
    confidence = 0.0f;
  }
  confidence *= 0.50f;
  return confidence;
}

#ifdef DEBUG_chardet
void  nsLatin1Prober::DumpStatus() {
  printf( " Latin1Prober: %1.3f [%s]\r\n", GetConfidence(), GetCharSetName() );
}
#endif


